using System;
using System.Net;
using System.Runtime.Serialization;

namespace Microsoft.Coding4Fun.TweetCraft.Tests.Support.Mocks
{

	/// <summary>
	/// Represents a mock web request.
	/// </summary>
	internal class MockRequest : HttpWebRequest
	{
		private readonly Uri uri;
		private readonly MockWebResponse response;

		/// <summary>
		/// Initializes a new instance of the <see cref="MockRequest"/> class.
		/// </summary>
		/// <param name="uri">The URI.</param>
		/// <param name="responseContent">Content of the response.</param>
		public MockRequest(Uri uri, string responseContent)
#pragma warning disable 612,618
			: base(CreateMockSerializationInfo(), new StreamingContext())
#pragma warning restore 612,618
		{
			if (uri == null)
				throw new ArgumentNullException("uri");

			this.uri = uri;
			response = new MockWebResponse(responseContent);
		}

		/// <summary>
		/// Begins an asynchronous request to an Internet resource.
		/// </summary>
		/// <param name="callback">The <see cref="T:System.AsyncCallback"/> delegate</param>
		/// <param name="state">The state object for this request.</param>
		/// <returns>
		/// An <see cref="T:System.IAsyncResult"/> that references the asynchronous request for a response.
		/// </returns>
		/// <exception cref="T:System.InvalidOperationException">
		/// The stream is already in use by a previous call to <see cref="M:System.Net.HttpWebRequest.BeginGetResponse(System.AsyncCallback,System.Object)"/>
		/// -or-
		/// <see cref="P:System.Net.HttpWebRequest.TransferEncoding"/> is set to a value and <see cref="P:System.Net.HttpWebRequest.SendChunked"/> is false.
		/// -or-
		/// The thread pool is running out of threads.
		/// </exception>
		/// <exception cref="T:System.Net.ProtocolViolationException">
		/// 	<see cref="P:System.Net.HttpWebRequest.Method"/> is GET or HEAD, and either <see cref="P:System.Net.HttpWebRequest.ContentLength"/> is greater than zero or <see cref="P:System.Net.HttpWebRequest.SendChunked"/> is true.
		/// -or-
		/// <see cref="P:System.Net.HttpWebRequest.KeepAlive"/> is true, <see cref="P:System.Net.HttpWebRequest.AllowWriteStreamBuffering"/> is false, and either <see cref="P:System.Net.HttpWebRequest.ContentLength"/> is -1, <see cref="P:System.Net.HttpWebRequest.SendChunked"/> is false and <see cref="P:System.Net.HttpWebRequest.Method"/> is POST or PUT.
		/// </exception>
		/// <exception cref="T:System.Net.WebException">
		/// 	<see cref="M:System.Net.HttpWebRequest.Abort"/> was previously called.
		/// </exception>
		/// <PermissionSet>
		/// 	<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Net.DnsPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Net.WebPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// </PermissionSet>
		public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
		{

			var result = new MockAsyncResult
			{
				AsyncState = state
			};
			if (callback != null)
				callback.Invoke(result);
			return result;
		}

		/// <summary>
		/// Ends an asynchronous request to an Internet resource.
		/// </summary>
		/// <param name="asyncResult">The pending request for a response.</param>
		/// <returns>
		/// A <see cref="T:System.Net.WebResponse"/> that contains the response from the Internet resource.
		/// </returns>
		/// <exception cref="T:System.ArgumentNullException">
		/// 	<paramref name="asyncResult"/> is null.
		/// </exception>
		/// <exception cref="T:System.InvalidOperationException">
		/// This method was called previously using <paramref name="asyncResult."/>
		/// -or-
		/// The <see cref="P:System.Net.HttpWebRequest.ContentLength"/> property is greater than 0 but the data has not been written to the request stream.
		/// </exception>
		/// <exception cref="T:System.Net.WebException">
		/// 	<see cref="M:System.Net.HttpWebRequest.Abort"/> was previously called.
		/// -or-
		/// An error occurred while processing the request.
		/// </exception>
		/// <exception cref="T:System.ArgumentException">
		/// 	<paramref name="asyncResult"/> was not returned by the current instance from a call to <see cref="M:System.Net.HttpWebRequest.BeginGetResponse(System.AsyncCallback,System.Object)"/>.
		/// </exception>
		/// <PermissionSet>
		/// 	<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
		/// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/>
		/// </PermissionSet>
		public override WebResponse EndGetResponse(IAsyncResult asyncResult)
		{
			return response;
		}

		/// <summary>
		/// Creates the mock serialization info.
		/// </summary>
		/// <returns></returns>
		private static SerializationInfo CreateMockSerializationInfo()
		{
			var serializationInfo = new SerializationInfo(typeof(MockRequest), new FormatterConverter());
			serializationInfo.AddValue("_HttpRequestHeaders", new WebHeaderCollection());
			serializationInfo.AddValue("_Proxy", new WebProxy());
			serializationInfo.AddValue("_KeepAlive", true);
			serializationInfo.AddValue("_Pipelined", true);
			serializationInfo.AddValue("_AllowAutoRedirect", true);
			serializationInfo.AddValue("_AllowWriteStreamBuffering", false);
			serializationInfo.AddValue("_HttpWriteMode", 0);
			serializationInfo.AddValue("_MaximumAllowedRedirections", 10);
			serializationInfo.AddValue("_AutoRedirects", 1);
			serializationInfo.AddValue("_Timeout", 180);
			serializationInfo.AddValue("_ContentLength", 1024);
			serializationInfo.AddValue("_MediaType", "html");
			serializationInfo.AddValue("_OriginVerb", "GET");
			serializationInfo.AddValue("_ConnectionGroupName", "");
			serializationInfo.AddValue("_Version", new Version(1, 1));
			serializationInfo.AddValue("_OriginUri", new Uri("http://localhost"));

			return serializationInfo;
		}
	}
}